
#include <type_traits>
#include <iostream> 
#include <string>

template<typename T>
void isvalue(T& i) {
    std::cout << "lvalue ref" <<  std::endl;
}

template<typename T>
void isvalue(const T& i) {
    std::cout << "const lvalue& " << std::endl;
}


template<typename T>
void isvalue(T&& i) {
    std::cout << "rvalue ref"  << std::endl;
}

template<typename T>
void isvalue(const T&& i) {
    std::cout << "const rvalue& " << std::endl;
}


struct Test {
    Test() {
        std::cout << "Test()" << std::endl;
    }

    Test(Test& ) {
        std::cout << "Test(Test& )" << std::endl;
    }
    Test(Test&& ) {
        std::cout << "Test(Test&& )" << std::endl;
    }
    ~Test() {
        std::cout << "~Test()" << std::endl;
    }

    static Test makeTest() {
        Test t;
        return t;
    }

    Test& makeTestRef() {
        return *this;
    }
};

int main() {
    int nu = 1;
    isvalue(nu);        //nu为lvalue 打印左值引用
    isvalue(1);         //1 为字面量，rvalue 打印右值引用 
    
    int* ii = &nu;
    int* i;         // 没有指定任何人
                    // 我活着，我指向的对象没了
    void* pp;                          


    const int& c_nu = nu;      // 左值引用
    int&& c_r = 1 + 1;      //   依然左值引用

    std::string s1{"3333"}, s2{"444"};
    std::string&& s3 = s1 + s2;
     
    isvalue(c_nu);
    isvalue(std::move(c_r));
    isvalue(s3);

    isvalue(Test::makeTest());

    Test t;
    isvalue(t.makeTestRef());

    std::cout << std::boolalpha;
    std::cout << std::is_lvalue_reference< decltype(c_r) >::value << '\n';
    std::cout << std::is_rvalue_reference< decltype(c_r) >::value << '\n';

    
}